package com.atguigu.tingshu.order.adapter;

import com.atguigu.tingshu.account.client.UserAccountFeignClient;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.order.LocalMsg;
import com.atguigu.tingshu.order.mapper.LocalMsgMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.vo.account.AccountLockResultVo;
import com.atguigu.tingshu.vo.account.AccountLockVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

/**TODO 零钱支付
 * @Author：yyj
 * @Package：com.atguigu.tingshu.order.adapter
 * @Project：tingshu_parent240829
 * @name：RechargePayWayImpl
 * @Date：2025/2/11 18:38
 * @Filename：RechargePayWayImpl
 */
@Component
public class RechargePayWayImpl implements PayWay{
    @Autowired
    private UserAccountFeignClient userAccountFeignClient;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private LocalMsgMapper localMsgMapper;
    /**
     * 本地定时任务（TODO:xxl-job）
//     *
//     * @param orderInfoVo
//     * @param orderNo
//     * @param userId
     */
    @Scheduled(fixedDelay = 1000 * 60 * 60)
    public void scanLocalMsg() {
        //扫描本地消息(性能可能降低)
        LambdaQueryWrapper<LocalMsg> wrapper = new LambdaQueryWrapper<LocalMsg>().eq(LocalMsg::getStatus, 0);
        List<LocalMsg> localMsgs = localMsgMapper.selectList(wrapper);
        for (LocalMsg localMsg : localMsgs) {
            rabbitService.sendMessage(MqConst.EXCHANGE_ACCOUNT, MqConst.ROUTING_ACCOUNT_UNLOCK, localMsg.getMsgContent());
            rabbitService.sendMessage(MqConst.EXCHANGE_ACCOUNT, MqConst.ROUTING_ACCOUNT_MINUS, localMsg.getMsgContent());
        }
    }



    /**
     * 支付某一种支付方式的支持方法
     */
    @Override
    public Boolean supportPayWay(String payWay) {
        return "1103".equals(payWay);
    }

    /**
     * 具体支付方法对应的支付逻辑
     * OrderInfoVo: 要保存的数据
     * orderNo：订单编号
     * userId： 用户id
     */
    @Override
    public void payWay(OrderInfoVo orderInfoVo, String orderNo, Long userId) {
        //2.保存订单
        try {
            //1.判断钱是否够用(rpc远程调用账户微服务获取账户锁定金额)
            AccountLockVo accountLockVo = prepareAccountData(orderInfoVo,orderNo,userId);
            Result<AccountLockResultVo> accountLockResultVoResult=userAccountFeignClient.checkAndLockAccount(accountLockVo);
            Integer code = accountLockResultVoResult.getCode();
            if (code!=200){
                //锁定失败
                throw new GuiguException(ResultCodeEnum.ACCOUNT_LOCK_ERROR);
            }
            orderInfoService.saveOrderInfo(orderInfoVo,orderNo,userId);
            // 4.初始化消息表
            orderInfoService.saveLocalMsg(orderNo);
            // 真正扣减余额
            rabbitService.sendMessage(MqConst.EXCHANGE_ACCOUNT, MqConst.ROUTING_ACCOUNT_MINUS, orderNo);

            //todo 支付成功后要对数据进行修改
            orderInfoService.paySuccess(orderNo);

        } catch (GuiguException  e) {
            // 反向去修改账户微服务下的账户信息（user_account的锁定账户余额和可用账户余额）
            rabbitService.sendMessage(MqConst.EXCHANGE_ACCOUNT,MqConst.ROUTING_ACCOUNT_UNLOCK,orderNo);
        }catch (Exception e){
            //避免上面真正扣减余额失败
            rabbitService.sendMessage(MqConst.EXCHANGE_ACCOUNT, MqConst.ROUTING_ACCOUNT_MINUS, orderNo);
        }
    }


    /*
     * @description: TODO 获取账户的数据
     * @author: yyj
     * @date: 2025-02-11
    */
    private AccountLockVo prepareAccountData(OrderInfoVo orderInfoVo, String orderNo, Long userId) {
        AccountLockVo accountLockVo = new AccountLockVo();
        accountLockVo.setOrderNo(orderNo);
        accountLockVo.setUserId(userId);
        accountLockVo.setAmount(orderInfoVo.getOrderAmount());
        accountLockVo.setContent(orderInfoVo.getOrderDetailVoList().get(0).getItemName());
        return accountLockVo;
    }
}